package com.boarsoft.boar.app.handler;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;

import com.boarsoft.agent.AgentService;
import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.BaseConfig;
import com.boarsoft.boar.app.AppHandler;
import com.boarsoft.boar.app.AppInstBiz;
import com.boarsoft.boar.entity.AppInfo;
import com.boarsoft.boar.entity.AppInst;
import com.boarsoft.rpc.core.RpcContext;
import com.boarsoft.soagov.health.HealthChecker;

public class ShellAppHandler implements AppHandler, HealthChecker {
	private static final Logger log = LoggerFactory.getLogger(ShellAppHandler.class);

	@Autowired
	@Lazy
	@Qualifier("agentX")
	protected AgentService agentX;

	@Autowired
	protected AppInstBiz appInstBiz;

	protected HealthChecker checker;

	@Override
	public ReplyInfo<Object> sync(AppInfo app, AppInst ai, String code, byte[] bytes, String fdp) {
		// 再调用AgentX让目标应用（配置中心）reload
		String cmd = app.getReloadCode();
		String addr = ai.getAddr();
		String axa = new StringBuilder().append(ai.getIp()).append(":")//
				.append(BaseConfig.AGENTX_PORT).toString();
		String adp = ai.getDeployPath();
		log.info("Ask {} reload config of app inst {} with: {}", axa, addr, cmd);
		RpcContext.specify2(axa);
		try {
			// 执行应用实例目录下的reload.sh脚本，从配置中心拉取配置并热加载，如果支持的话
			// 此时的fdp参数无用
			return agentX.executeShell(adp, cmd, //
					new String[] { adp, ai.getIp(), String.valueOf(ai.getPort()) });
		} catch (IOException | InterruptedException e) {
			log.error("AgentX {} update config of app inst {} failed, {}"//
					, axa, addr, e.getMessage(), e);
			return new ReplyInfo<Object>(e.getMessage());
		} finally {
			RpcContext.specify2(null);
		}
	}

	public short test(String addr) {
		if (!this.exists(addr)) {
			return AppInst.STATUS_MISSING;
		}
		if (checker.check(addr)) {
			return AppInst.STATUS_RUNNING;
		}
		return AppInst.STATUS_STOPPED;
	}

	@Override
	public boolean exists(String addr) {
		String[] a = addr.split(":");
		String ip = a[0];
		int port = Integer.parseInt(a[1]);
		//
		AppInst inst = appInstBiz.find(ip, port);
		addr = String.format("%s:%d", ip, BaseConfig.AGENTX_PORT);
		RpcContext.specify2(addr);
		try {
			return agentX.exists(inst.getDeployPath());
		} catch (Exception e) {
			log.error("Error on check exists via {}", addr, e);
			return false;
		} finally {
			RpcContext.specify2(null);
		}
	}

	@Override
	public boolean check(String addr) {
		return checker.check(addr);
	}
}